-- http://andrewliu.in/2016/08/29/%E5%BF%AB%E5%AD%A6Lua/?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io

message = "this is test!!!"
print(message)
sum = 0
num = 1
no_define = nil

print(no_define)

-- if-else
local age = 100
if age <= 40 and age >= 20 then
    print("young man!")
elseif age > 40 and age < 100 then
    print("old man")
elseif age < 20 then
    print("too young")
else
    print("monster" .. age) -- .. 连接字符串
end

-- while ,do
local num = 0
while num < 10 do
    -- print(num)
    num = num + 1
end

-- for 循环
for i = 1, 100 do -- for(int i=1,i!=100,++i){}
--do sometiong
end

for i = 1, 100, 2 do -- for(int i=1,i!=100,i=+2){}
end

-- until 操作 类似于 c++中 do while()
local num = 0
repeat
    num = num + 11;
until num >= 1000
print("repeat until " .. num)

--[[
支持有名和匿名函数
函数最后有个end, 编辑器 自动生成  不用担心
函数支持一次`返回多个变量
局部函数的定义只需要在函数前加个local, 和局部变量类似
]]
--函数定义
function add(a, b)
    return a % b, 100
end

local add_value, _ = add(4, 3);
print("4%3：" .. add_value .. ":" .. _)

--匿名函数
_function = function(a, b)
    return a % b;
end
print("匿名函数：" .. _function(5, 8))



-- Lua唯一的组合数据结构
-- 可以使用任何非nil值作为key
-- Table(key-value数据结构)
local
map = {
    name = "andrew", -- 此处name默认使用字符串作为key
    age = 18,
    sex = "male"
}

function for_each(map)
    --遍历table
    local count = 0
    for k, v in pairs(map) do
        print("key:" .. k .. " value:" .. v)
        count = count + 1
    end
    return count
end

local count = for_each(map);
print("table one value:" .. map['name'] .. "map length:" .. count) -- equal to :map.name
-- del map value
--del and for_each
print("del.....")
map.name = nil
local count = for_each(map)
print("del after....." .. "map length:" .. count)




--Lua中数组的下标是 从1开始, 从1开始, 从1开始. 重要的事情说三遍.
local array = { "石头哥哥", "测试", 18 }
print("array length:" .. #array)
for index = 1, #array do
    print("value:" .. array[index])
end


-- lua 中的元方法
-- __add(a, b)                     for a + b
-- __sub(a, b)                     for a - b
-- __mul(a, b)                     for a * b
-- __div(a, b)                     for a / b
-- __mod(a, b)                     for a % b
-- __pow(a, b)                     for a ^ b
-- __unm(a)                        for -a
-- __concat(a, b)                  for a .. b
-- __len(a)                        for #a
-- __eq(a, b)                      for a == b
-- __lt(a, b)                      for a < b
-- __le(a, b)                      for a <= b
-- __index(a, b)  <fn or a table>  for a.b      (方法 or  表)
-- __newindex(a, b, c)             for a.b = c
-- __call(a, ...)                  for a(...)




--Table的metatable提供一种类似于操作符重载的机制
--table的元表提供一种机制,支持操作符重载
data_one = { a = 1, b = 2 } -- data_one和data_two 可以看做表示1/2和3/4
data_two = { a = 3, b = 4 }
meta_fraction = {} -- 新定义一个元表
function meta_fraction.__add(t1, t2) -- __add是build-in的原方法
local sum = {}
sum.b = t1.b * t2.b -- 8
sum.a = t1.a * t2.b + t2.a * t1.b -- 4+6 =10
return sum -- {a=10,b=8}
end

-- table bind method
setmetatable(data_one, meta_fraction)
setmetatable(data_two, meta_fraction)
local data_three = data_one + data_two -- 执行 + 操作
print("elements :" .. for_each(data_three))


--元表的__index 可以重载用于查找的点操作符, 我理解有点类似于python中的__getattr__, 对类中的属性做查找
-- 当表要索引一个值时如table[key], Lua会首先在table本身中查找key的值,
-- 如果没有并且这个table存在一个带有__index属性的Metatable, 则Lua会按照__index所定义的函数逻辑查找
default_map = { name = 'andrew', sex = 'male' }
new_map = { age = 18 }
setmetatable(default_map, { __index = new_map }) -- __index
print(default_map.name, "====", default_map.age) -- 继承了new_map的属性



--继承同样是通过元表和元方法来实现的.
-- table实现继承
Dog = {}
-- 这个new函数我理解为继承类的构造函数, 冒号(:)函数会使参数默认增加一个self作为参数
function Dog:new()
    -- 下面这句相当于继承的类增加的新的成员变量
    local new_obj = { sound = 'woof' }
    self.__index = self
    return setmetatable(new_obj, self)
end

function Dog:make_sound() -- 等价于Dog.make_sound(Dog)
print("say " .. self.sound)
end

-- 使用
local new_dog = Dog:new() -- new_dog获得Dog的方法和变量列表
new_dog:make_sound()


--模块
--require函数, 第一次执行后有缓存, 所以载入同样的lua文件时, 只有第一次的时候会去执行, 多次执行同一句require, 只有第一次生效
--dofile函数, 类似于require, 但无缓存, 每次语句都会重新执行一次
--loadfile加载一个lua文件, 但是并不运行它, 只要在需要的时候再像函数一样执行它

-- module
-- 1. require
--local test = require('module') -- require文件会被缓存
-- test.say_my_name()  -- 不能调用local
-- test.say_hello()
-- 2. dofile 类似require 但不缓存
-- 3. loadfile加载一个lua文件, 但是并不运行它




